package com.it.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.it.entity.AnswerRecord;
import com.it.entity.ExamPaper;
import com.it.entity.ExamRecord;
import com.it.entity.QuestionBank;
import com.it.mapper.QuestionBankMapper;
import com.it.service.IAnswerRecordService;
import com.it.service.IExamPaperService;
import com.it.service.IExamRecordService;
import com.it.service.IQuestionBankService;
import com.it.util.RedisKeyConstant;
import com.it.util.ThreadLocalUtil;
import com.it.vo.QuestionInfoVo;
import com.it.vo.QuestionVo;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * @author 16272
 */
@Service
public class QuestionBankServiceImpl implements IQuestionBankService {
    @Resource
    private QuestionBankMapper questionBankMapper;

    @Resource
    private IExamPaperService examPaperService;
    @Resource
    private IExamRecordService examRecordService;

    @Resource
    private IAnswerRecordService answerRecordService;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public void addQuestion(QuestionVo questionVo) {
        if (questionVo.getOptions() != null) {
            questionVo.setQuestionOptions(JSON.toJSONString(questionVo.getOptions()));
        }
        questionVo.setQuestionId(IdUtil.getSnowflakeNextId());
        questionVo.setCreateTime(new Date());
        questionVo.setUpdateTime(new Date());
        questionVo.setIsDeleted(0);
        questionBankMapper.addQuestion(questionVo);
    }

    @Override
    public Map<String, Object> getQuestionList() {
        long examId = IdUtil.getSnowflakeNextId();
        List<QuestionBank> allQuestions = questionBankMapper.findAllQuestions();
        List<QuestionBank> randomList = getRandomQuestions(allQuestions, 10, examId);
        List<QuestionInfoVo> questionInfoVoList = randomList.stream()
                .map(this::convertToQuestionInfoVo)
                .collect(Collectors.toList());


        randomList.forEach(question ->
                redisTemplate.opsForHash().put(
                        RedisKeyConstant.QUESTION_KEY.getKey() + examId,
                        String.valueOf(question.getQuestionId()),
                        question.getQuestionAnswer()
                )
        );
        redisTemplate.expire(RedisKeyConstant.QUESTION_KEY.getKey() + examId, Duration.ofMinutes(5));

        Map<String, Object> map = new HashMap<>();
        map.put("questions", questionInfoVoList);
        map.put("examId", String.valueOf(examId));
        return map;
    }

    @Override
    public AtomicLong checkAnswer(Long examId, Map<Long, String> answers) {
        Long userId = ThreadLocalUtil.getUserId();
        Map<String, String> trueAnswers;
        Map<String, String> trueAnswersByRedis = getTrueAnswersFromRedis(examId);
//        如果redis查不到就走db
        if (trueAnswersByRedis.isEmpty()) {
            trueAnswers = examPaperService.getExamPaperAnswers(examId);
        }else {
            trueAnswers=trueAnswersByRedis;
        }
        AtomicLong score = new AtomicLong();
        trueAnswers.forEach((questionId, trueAnswer) -> {
            Long qid=Long.valueOf(questionId);
            String userAnswer = answers.get(qid);
            if (trueAnswer.equals(userAnswer)) {
                score.addAndGet(10);
            }
            AnswerRecord answerRecord = new AnswerRecord(examId, userId, qid, userAnswer, trueAnswer, new Date());
            answerRecordService.addAnswerRecord(answerRecord);
        });

        ExamRecord examRecord = new ExamRecord(examId, userId, score.intValue(), new Date());
        examRecordService.addExamRecord(examRecord);

        return score;
    }

    private List<QuestionBank> getRandomQuestions(List<QuestionBank> questions, int numberOfQuestions,Long examId) {
        List<QuestionBank> randomList = new ArrayList<>();
        long paperId = IdUtil.getSnowflakeNextId();
        while (randomList.size()<numberOfQuestions){
            int index = new Random().nextInt(questions.size());
            QuestionBank questionBank = questions.get(index);
            if (!randomList.contains(questionBank)){
                ExamPaper examPaper = new ExamPaper(paperId,examId,questionBank.getQuestionId(),questionBank.getQuestionAnswer());
                examPaperService.addExamPaper(examPaper);
                randomList.add(questionBank);
            }
        }
        return randomList;
    }


//    处理成QuestionInfoVo类型
    private QuestionInfoVo convertToQuestionInfoVo(QuestionBank questionBank) {
        QuestionInfoVo questionInfoVo = new QuestionInfoVo();
        BeanUtils.copyProperties(questionBank, questionInfoVo);
        questionInfoVo.setQuestionId(String.valueOf(questionBank.getQuestionId()));
        return questionInfoVo;
    }

    private Map<String, String> getTrueAnswersFromRedis(Long examId) {
            return (Map<String, String>) (Map<?, ?>) redisTemplate.opsForHash().entries(RedisKeyConstant.QUESTION_KEY.getKey() + examId);
    }
}
